/*
* jQuery Simple-RTE plugin 0.1 - Yet anothor simple rich text editor based on jQuery
*
* Copyright (c) 2010 Darcy Young
* Distributed under the MIT License.
* 
* copy lots of code from `jQuery rte plugin` posted by Batiste Bieler, url below
* http://code.google.com/p/rte-light/
*/
(function($) {
	if (typeof $.fn.simpleRTE !== "undefined") return;
	var defaultOpt = { css: null, discardOriginClass: true, includeToolbarHeight: true };
	var _fonts = {"'Times New Roman',serif": 'Serif', 'Arial,sans-serif': 'Sans-serif', "'Courier New',monospace": 'Monospace'};

	$.fn.simpleRTE = function(options) {
		var _opts = $.extend(defaultOpt, options);
		return this.each(function() {
			var T = $(this), _toolbar = null, _container = null, _iframe = null, _iWin = null, _iDoc = null, _buttons = null, _palette = null;

			function build() {
				// original width / height
				var width = T.outerWidth(true), height = T.outerHeight(true);
				_container = $('<div class="simple-rte"></div>');
				T.before(_container);
				_buildFontList();
				_buildToolbar();
				_buildIFrame(_opts.css || [], T.val());
				_container.append(T);
				// register submit event
				T.parents('form').submit(function() { i2t(); });
				// get delta: margin + padding + border
				var deltaWidth = _container.outerWidth(true) - _container.width(),
					deltaHeight = _container.outerHeight(true) - _container.height(),
					toolbarHeight = _toolbar.outerHeight(true);
				// set height to keep original width / height
				_container.width(width - deltaWidth).height(height - deltaHeight + (_opts.includeToolbarHeight ? 0 : toolbarHeight));
				// discard old class name, bug fix for blueprintcss `textarea {padding:5px!important}`
				if (_opts.discardOriginClass) T.attr('className', null);
				// set editor height: containerHeight - toolbarHeight
				var editorHeight = _container.height() - toolbarHeight;
				// set iframe / textarea style
				_iframe.css({padding: 0, margin: 0, border: 0, width: '100%'}).height(editorHeight);
				T.css({padding: 0, margin: 0, border: 0, width: '100%'}).height(editorHeight);
			}

			function _buildFontList() {
				// font-family may not be exactly equal with value already set
				var el = $('<span style="display:none;">Hello</span>'), fonts = {};
				for (var name in _fonts) {
					el.css('font-family', name);
					fonts[el.css('font-family')] = _fonts[name];
				}
				el = null;
				_fonts = fonts;
			}

			function _buildToolbar() {
				_buttons = {
					bold: $('<a href="#none" class="simple-rte-toolbar-bold">&nbsp;</a>')
						.click(function(){ formatText('bold'); return false; }),
					italic: $('<a href="#none" class="simple-rte-toolbar-italic">&nbsp;</a>')
						.click(function(){ formatText('italic'); return false; }),
					list: $('<a href="#none" class="simple-rte-toolbar-unorderedlist">&nbsp;</a>')
						.click(function(){ formatText('insertunorderedlist'); return false; }),
					link: $('<a href="#none" class="simple-rte-toolbar-link">&nbsp;</a>')
						.click(function(){ var L = prompt('URL', 'http://'); L && formatText('CreateLink', L); return false; }),
					image: $('<a href="#none" class="simple-rte-toolbar-image">&nbsp;</a>')
						.click(function(){ var L = prompt("Image URL", 'http://'); L && formatText('InsertImage', L); return false; }),
					fontcolor: $('<a href="#none" class="simple-rte-toolbar-fontcolor">&nbsp;</a>')
						.click(function() { var thz = $(this), P = thz.position(); showPalette({color: getFontColor(), selected: function(e, color) { setFontColor(color); }, left: P.left + 'px', top: (P.top + thz.outerHeight(true)) + 'px'}); return false; }),
					enable: $('<a href="#none" class="simple-rte-toolbar-disable">&nbsp;</a>')
						.click(function() { toggleEnable(); return false; }),
					font: $('<select><option value="">Font</option></select>')
						.change(function(){ var F = $(this).val(); F && formatText("FontName", F); })
				};
				for (var name in _fonts) {
					_buttons.font.append('<option value="' + name + '">' + _fonts[name] + '</option>');
				}
				_toolbar = $('<div class="simple-rte-toolbar"></div>')
					.append(_buttons.bold).append(_buttons.italic).append('<b>&nbsp;</b>')
					.append(_buttons.list).append(_buttons.link).append(_buttons.image).append('<b>&nbsp;</b>')
					.append(_buttons.fontcolor).append(_buttons.font).append('<b>&nbsp;</b>')
					.append(_buttons.enable);
				_container.append(_toolbar);
			}

			function _buildIFrame(css, content) {
				_iframe = document.createElement('iframe');
				_container.append(_iframe);
				_iframe.frameBorder = 0; _iframe.frameMargin = 0; _iframe.framePadding = 0;
				_iframe.className = 'simple-rte-iframe';
				if (!css) css = [];
				else if (typeof css === 'string') css = [css];
				var cssText = '';
				for (var I = 0; I < css.length; ++I)
					cssText += '<link type="text/css" rel="stylesheet" href="' + css[I] + '" />';
				var doc = '<html><head>' + cssText + '</head><body class="simple-rte-iframe-body">' + (content || '<br />') + '</body></html>';
				try {
					_iframe.contentWindow.document.open();
					_iframe.contentWindow.document.write(doc);
					_iframe.contentWindow.document.close();
				} catch(error) {
					return false;
				}
				if (typeof document.designMode !== "undefined") {
					_iframe.contentWindow.document.designMode = "on";
				} else if (document.contentEditable) {
					_iframe.contentWindow.document.contentEditable = "true";
				} else {
					return false;
				}
				_iWin = _iframe.contentWindow;
				_iDoc = _iWin.document;
				_iframe = $(_iframe);
				$(_iDoc).mouseup(updateToolbar).keyup(updateToolbar);
			}

			function _buildPalette() {
				var palette = $('<div class="simple-palette">\
					<table cellspacing="0" cellpadding="0">\
					<tbody>\
					<tr class="simple-palette-margin">\
						<td><div style="background-color: rgb(0, 0, 0);" title="RGB (0, 0, 0)"></div></td>\
						<td><div style="background-color: rgb(68, 68, 68);" title="RGB (68, 68, 68)"></div></td>\
						<td><div style="background-color: rgb(102, 102, 102);" title="RGB (102, 102, 102)"></div></td>\
						<td><div style="background-color: rgb(153, 153, 153);" title="RGB (153, 153, 153)"></div></td>\
						<td><div style="background-color: rgb(204, 204, 204);" title="RGB (204, 204, 204)"></div></td>\
						<td><div style="background-color: rgb(238, 238, 238);" title="RGB (238, 238, 238)"></div></td>\
						<td><div style="background-color: rgb(243, 243, 243);" title="RGB (243, 243, 243)"></div></td>\
						<td><div style="background-color: rgb(255, 255, 255);" title="RGB (255, 255, 255)"></div></td>\
					</tr>\
					<tr class="simple-palette-margin">\
						<td><div style="background-color: rgb(255, 0, 0);" title="RGB (255, 0, 0)"></div></td>\
						<td><div style="background-color: rgb(255, 153, 0);" title="RGB (255, 153, 0)"></div></td>\
						<td><div style="background-color: rgb(255, 255, 0);" title="RGB (255, 255, 0)"></div></td>\
						<td><div style="background-color: rgb(0, 255, 0);" title="RGB (0, 255, 0)"></div></td>\
						<td><div style="background-color: rgb(0, 255, 255);" title="RGB (0, 255, 255)"></div></td>\
						<td><div style="background-color: rgb(0, 0, 255);" title="RGB (0, 0, 255)"></div></td>\
						<td><div style="background-color: rgb(153, 0, 255);" title="RGB (153, 0, 255)"></div></td>\
						<td><div style="background-color: rgb(255, 0, 255);" title="RGB (255, 0, 255)"></div></td>\
					</tr>\
					<tr>\
						<td><div title="RGB (244, 204, 204)" style="background-color: rgb(244, 204, 204);"></div></td>\
						<td><div title="RGB (252, 229, 205)" style="background-color: rgb(252, 229, 205);"></div></td>\
						<td><div title="RGB (255, 242, 204)" style="background-color: rgb(255, 242, 204);"></div></td>\
						<td><div title="RGB (217, 234, 211)" style="background-color: rgb(217, 234, 211);"></div></td>\
						<td><div title="RGB (208, 224, 227)" style="background-color: rgb(208, 224, 227);"></div></td>\
						<td><div title="RGB (207, 226, 243)" style="background-color: rgb(207, 226, 243);"></div></td>\
						<td><div title="RGB (217, 210, 233)" style="background-color: rgb(217, 210, 233);"></div></td>\
						<td><div title="RGB (234, 209, 220)" style="background-color: rgb(234, 209, 220);"></div></td>\
					</tr>\
					<tr>\
						<td><div title="RGB (234, 153, 153)" style="background-color: rgb(234, 153, 153);"></div></td>\
						<td><div title="RGB (249, 203, 156)" style="background-color: rgb(249, 203, 156);"></div></td>\
						<td><div title="RGB (255, 229, 153)" style="background-color: rgb(255, 229, 153);"></div></td>\
						<td><div title="RGB (182, 215, 168)" style="background-color: rgb(182, 215, 168);"></div></td>\
						<td><div title="RGB (162, 196, 201)" style="background-color: rgb(162, 196, 201);"></div></td>\
						<td><div title="RGB (159, 197, 232)" style="background-color: rgb(159, 197, 232);"></div></td>\
						<td><div title="RGB (180, 167, 214)" style="background-color: rgb(180, 167, 214);"></div></td>\
						<td><div title="RGB (213, 166, 189)" style="background-color: rgb(213, 166, 189);"></div></td>\
					</tr>\
					<tr>\
						<td><div title="RGB (224, 102, 102)" style="background-color: rgb(224, 102, 102);"></div></td>\
						<td><div title="RGB (246, 178, 107)" style="background-color: rgb(246, 178, 107);"></div></td>\
						<td><div title="RGB (255, 217, 102)" style="background-color: rgb(255, 217, 102);"></div></td>\
						<td><div title="RGB (147, 196, 125)" style="background-color: rgb(147, 196, 125);"></div></td>\
						<td><div title="RGB (118, 165, 175)" style="background-color: rgb(118, 165, 175);"></div></td>\
						<td><div title="RGB (111, 168, 220)" style="background-color: rgb(111, 168, 220);"></div></td>\
						<td><div title="RGB (142, 124, 195)" style="background-color: rgb(142, 124, 195);"></div></td>\
						<td><div title="RGB (194, 123, 160)" style="background-color: rgb(194, 123, 160);"></div></td>\
					</tr>\
					<tr>\
						<td><div title="RGB (204, 0, 0)" style="background-color: rgb(204, 0, 0);"></div></td>\
						<td><div title="RGB (230, 145, 56)" style="background-color: rgb(230, 145, 56);"></div></td>\
						<td><div title="RGB (241, 194, 50)" style="background-color: rgb(241, 194, 50);"></div></td>\
						<td><div title="RGB (106, 168, 79)" style="background-color: rgb(106, 168, 79);"></div></td>\
						<td><div title="RGB (69, 129, 142)" style="background-color: rgb(69, 129, 142);"></div></td>\
						<td><div title="RGB (61, 133, 198)" style="background-color: rgb(61, 133, 198);"></div></td>\
						<td><div title="RGB (103, 78, 167)" style="background-color: rgb(103, 78, 167);"></div></td>\
						<td><div title="RGB (166, 77, 121)" style="background-color: rgb(166, 77, 121);"></div></td>\
					</tr>\
					<tr>\
						<td><div title="RGB (153, 0, 0)" style="background-color: rgb(153, 0, 0);"></div></td>\
						<td><div title="RGB (180, 95, 6)" style="background-color: rgb(180, 95, 6);"></div></td>\
						<td><div title="RGB (191, 144, 0)" style="background-color: rgb(191, 144, 0);"></div></td>\
						<td><div title="RGB (56, 118, 29)" style="background-color: rgb(56, 118, 29);"></div></td>\
						<td><div title="RGB (19, 79, 92)" style="background-color: rgb(19, 79, 92);"></div></td>\
						<td><div title="RGB (11, 83, 148)" style="background-color: rgb(11, 83, 148);"></div></td>\
						<td><div title="RGB (53, 28, 117)" style="background-color: rgb(53, 28, 117);"></div></td>\
						<td><div title="RGB (116, 27, 71)" style="background-color: rgb(116, 27, 71);"></div></td>\
					</tr>\
					<tr>\
						<td><div title="RGB (102, 0, 0)" style="background-color: rgb(102, 0, 0);"></div></td>\
						<td><div title="RGB (120, 63, 4)" style="background-color: rgb(120, 63, 4);"></div></td>\
						<td><div title="RGB (127, 96, 0)" style="background-color: rgb(127, 96, 0);"></div></td>\
						<td><div title="RGB (39, 78, 19)" style="background-color: rgb(39, 78, 19);"></div></td>\
						<td><div title="RGB (12, 52, 61)" style="background-color: rgb(12, 52, 61);"></div></td>\
						<td><div title="RGB (7, 55, 99)" style="background-color: rgb(7, 55, 99);"></div></td>\
						<td><div title="RGB (32, 18, 77)" style="background-color: rgb(32, 18, 77);"></div></td>\
						<td><div title="RGB (76, 17, 48)" style="background-color: rgb(76, 17, 48);"></div></td>\
					</tr>\
					</tbody>\
					</table>\
					</div>');
				palette.hide().appendTo(_container).click(function(e) {
					if (e.target.nodeName.toLowerCase() != 'div') return;
					palette.trigger('simple_palette_selected', [$(e.target).css('background-color')]);
				});
				$(document).click(function() { palette.hide(); });
				$(_iDoc).click(function() { palette.hide(); });
				return palette;
			}

			function t2i() { $('body', _iDoc).html(T.val()); }

			function i2t() { T.val($('body', _iDoc).html()); }

			function toggleEnable() {
				var method = null;
				if (_buttons.enable.hasClass('simple-rte-toolbar-disable')) {
					_buttons.enable.removeClass('simple-rte-toolbar-disable').addClass('simple-rte-toolbar-enable');
					disableDesignMode();
					method = 'addClass';
					i2t();
				} else {
					_buttons.enable.removeClass('simple-rte-toolbar-enable').addClass('simple-rte-toolbar-disable');
					enableDesignMode();
					method = 'removeClass';
					t2i();
				}
				for (var name in _buttons) {
					if (name != 'enable')
						_buttons[name][method]('simple-rte-toolbar-disabled');
				}
			}

			function getSelectedNode() {
				var node = null;
				if (_iDoc.selection) {
					// IE
					try { node = _iDoc.selection.createRange().parentElement(); }
					catch (e) { node = null; }
				} else {
					// Mozilla selections
					try { node = _iWin.getSelection().getRangeAt(0).commonAncestorContainer; }
					catch(e){ node = null; }
				}
				return node;
			}

			function getFontColor() {
				var node = getSelectedNode(), color = null;
				if (node) {
					if (node.nodeType == 3) node = node.parentNode;
					if ((node = $(node))) color = node.css('color');
				}
				return color;
			}

			function setFontColor(color) {
				formatText('forecolor', color);
			}

			function formatText(command, option) {
				_iWin.focus();
				try {
					_iDoc.execCommand(command, false, option);
				} catch(e) { return false; }
				_iWin.focus();
			}

			function enableDesignMode() {
				_iframe.show();
				T.hide();
			}

			function disableDesignMode() {
				_iframe.hide();
				T.show();
			}

			function showPalette(opt) {
				if (!_palette) {
					_palette = _buildPalette();
				}
				if (opt.selected) {
					_palette.one('simple_palette_selected', opt.selected);
				}
				if (opt.left && opt.top) {
					_palette.css({left: opt.left, top: opt.top});
				}
				_palette.show();
				var children = $('div', _palette);
				children.html('');
				if (opt.color) {
					children.filter(function() {
						return opt.color == $(this).css('background-color');
					}).html('&radic;');
				}
			}

			function updateToolbar(e) {
				updateFontName();
			}

			function updateFontName() {
				_buttons.font.val('');
				var node = getSelectedNode();
				if (!node) return;
				if (node.nodeType == 3) node = node.parentNode;
				if (node && (node = $(node))) {
					var name = $(node).css('font-family');
					_buttons.font.val(_fonts[name] ? name: "");
				}
			}

			build();
			enableDesignMode();
		});
	};
})(jQuery);